/**
 * Bakalarska prace - Inteligentni budik
 * @package sleepCatcher
 * @file FormCatchSleep.cpp
 * @author Jan Pesava - xpesav00
 * @email xpesav00@stud.fit.vutbr.cz
 * @date 24. 12. 2011
 */

#include <FSystem.h>

#include "forms/formCatchSleep.h"
#include "SCFormManager.h"
#include "SCNavigator.h"
#include "SCDataCollector.h"
#include "models/SCHelpers.h"
#include "SCTranslator.h"

using namespace Osp::System;
using namespace Osp::Base::Utility;

FormCatchSleep::FormCatchSleep()
{
	//init
	this->pActiveSCAlarm = NULL;
	this->pLastSample = NULL;
	this->pSleepViewResampler = NULL;
	this->pDataResampler = NULL;
	this->pSleepView = NULL;
	this->pDataCollector = NULL;

	this->pSensorManager = new SensorManager();
	this->pSensorManager->Construct();

}

FormCatchSleep::~FormCatchSleep()
{
	if(this->isCatchStart)
	{
		this->StopCatch();
	}

	//Stop screenSaver
	if(SCFormManager::screenSaver)
	{
		this->StopScreenSaver();
	}

	delete this->pSensorManager;
	delete this->pDataCollector;
	delete this->pSleepView;
	delete this->pDataResampler;
	delete this->pSleepViewResampler;
	delete this->pScreenSaver;
	delete this->pScreenSaverPicture;
}

bool
FormCatchSleep::Initialize()
{
	Construct(L"IDF_CATCH_SLEEP");
	return true;
}

bool
FormCatchSleep::InitializeSensors()
{
	long int maxInterval;
	result r;

	this->pSensorManager->GetMaxInterval(SENSOR_TYPE_ACCELERATION, maxInterval);
	if(this->pSensorManager->IsAvailable(SENSOR_TYPE_ACCELERATION))
	{
		r = this->pSensorManager->AddSensorListener(*this, SENSOR_TYPE_ACCELERATION, maxInterval, false);
		if(IsFailed(r))
		{
			return false;
		}
	}
	else
	{
		return false;
	}

	return true;
}

result
FormCatchSleep::OnInitializing(void)
{
	result r = E_SUCCESS;

	//Init form
	this->pAlarmText = static_cast<Label*>(GetControl("IDC_LABEL_ALARM_TEXT"));
	this->pAlarmImg = static_cast<Label*>(GetControl("IDC_LABEL_ALARM_IMG"));
	this->pDateText = static_cast<Label*>(GetControl("IDC_LABEL_DATE_TEXT"));
	this->pDateImg = static_cast<Label*>(GetControl("IDC_LABEL_DATE_IMG"));
	this->pSamplesCount = static_cast<Label*>(GetControl("IDC_LABEL_SAMPLES_COUNT"));
	this->pLabelBG = static_cast<Label*>(GetControl("IDC_LABEL_BACKGROUND"));

	this->pAlarmText->AddTouchEventListener(*this);
	this->pAlarmImg->AddTouchEventListener(*this);
	this->pDateText->AddTouchEventListener(*this);
	this->pDateImg->AddTouchEventListener(*this);
	this->pSamplesCount->AddTouchEventListener(*this);
	this->pLabelBG->AddTouchEventListener(*this);

	//Initialize Menu
	SCNavigator::SetMainMenu(this, GetTab(), SCFormManager::IDF_CATCH_SLEEP);
	this->GetTab()->AddTouchEventListener(*this);

	//Create SleepView
	this->pSleepView = new SCSleepView(this,0, 184, 480, 616, 200, 20);

	//Resamplers
	this->pSleepViewResampler = new SCResampler(2, false);
	this->pDataResampler = new SCResampler(10, false);

	//DataCollector
	this->pDataCollector = new SCDataCollector(this);

	//create ScreenSaver
	Image* pImage = new Image();
	pImage->Construct();
	this->pScreenSaverPicture = pImage->DecodeN(L"/Home/Icons/Commons/screenSaver.png",BITMAP_PIXEL_FORMAT_RGB565);
	this->pScreenSaver = new Canvas();
	this->pScreenSaver->Construct(this->GetBounds());
	this->pScreenSaver->DrawBitmap(Point(0,0), *pScreenSaverPicture);

	//save brightness
	this->defaultScreenBrightness = PowerManager::GetScreenBrightness();

	//delete pBitmap;
	delete pImage;

	return r;
}

result
FormCatchSleep::OnTerminating(void)
{
	result r = E_SUCCESS;

	return r;
}

void
FormCatchSleep::OnActionPerformed(const Osp::Ui::Control& source, int actionId)
{
	switch (actionId)
	{
		case SCFormManager::IDF_ALARM:
			this->StopCatch();
			SCFormManager::SwitchToForm(SCFormManager::IDF_ALARM, false, null, SCFormManager::NO_SLIDE);
			break;
		case SCFormManager::IDF_SETTINGS:
			this->StopCatch();
			SCFormManager::SwitchToForm(SCFormManager::IDF_SETTINGS, false, null, SCFormManager::NO_SLIDE);
			break;
		case SCFormManager::IDF_SESSIONS:
			this->StopCatch();
			SCFormManager::SwitchToForm(SCFormManager::IDF_SESSIONS, false, null, SCFormManager::NO_SLIDE);
			break;
		case SCFormManager::IDF_STATISTICS:
			this->StopCatch();
			SCFormManager::SwitchToForm(SCFormManager::IDF_STATISTICS, false, null, SCFormManager::NO_SLIDE);
			break;
		default:
			break;
	}
}

void
FormCatchSleep::OnTouchDoublePressed (const Osp::Ui::Control &source, const Osp::Graphics::Point &currentPosition, const TouchEventInfo &touchInfo)
{
	// Not implemented
}

void
FormCatchSleep::OnTouchFocusIn (const Osp::Ui::Control &source, const Osp::Graphics::Point &currentPosition, const TouchEventInfo &touchInfo)
{
	// Not implemented
}

void
FormCatchSleep::OnTouchFocusOut (const Osp::Ui::Control &source, const Osp::Graphics::Point &currentPosition, const TouchEventInfo &touchInfo)
{
	// Not implemented
}

void
FormCatchSleep::OnTouchLongPressed (const Osp::Ui::Control &source, const Osp::Graphics::Point &currentPosition, const TouchEventInfo &touchInfo)
{
	// Not implemented
}

void
FormCatchSleep::OnTouchMoved (const Osp::Ui::Control &source, const Osp::Graphics::Point &currentPosition, const TouchEventInfo &touchInfo)
{
	// Not implemented
}

void
FormCatchSleep::OnTouchPressed (const Osp::Ui::Control &source, const Osp::Graphics::Point &currentPosition, const TouchEventInfo &touchInfo)
{
	if(this->pTimer != NULL)
	{
		if(SCFormManager::screenSaver)
		{
			this->StopScreenSaver();
		} else {
			this->pTimer->Cancel();
		}

		this->pTimer->Start(30000);
	}
}

void
FormCatchSleep::OnTouchReleased (const Osp::Ui::Control &source, const Osp::Graphics::Point &currentPosition, const TouchEventInfo &touchInfo)
{
	// Not implemented
}

void
FormCatchSleep::OnTimerExpired (Timer &timer)
{
	//utlumeni displeje
	if(!SCFormManager::appOnBackground)
	{
		this->StartScreenSaver();
	}
}

result
FormCatchSleep::OnDraw()
{
	if(SCFormManager::screenSaver)
	{
		this->pScreenSaver->Show();
	}

	return E_SUCCESS;
}

void
FormCatchSleep::StartScreenSaver()
{
	//hide form
	this->SetShowState(false);

	SCFormManager::screenSaver = true;
	this->pScreenSaver->Show();
	PowerManager::SetScreenBrightness(1);
}

void
FormCatchSleep::StopScreenSaver()
{
	//show form
	this->SetShowState(true);

	this->RequestRedraw(true);
	SCFormManager::screenSaver = false;
	PowerManager::SetScreenBrightness(10);
}

void
FormCatchSleep::OnDataReceived (SensorType sensorType, SensorData &sensorData, result r)
{
	float x, y, z;
	SCSample *pDataSample = NULL, *pSleepViewSample = NULL;

	sensorData.GetValue((SensorDataKey)ACCELERATION_DATA_KEY_X, x);
	sensorData.GetValue((SensorDataKey)ACCELERATION_DATA_KEY_Y, y);
	sensorData.GetValue((SensorDataKey)ACCELERATION_DATA_KEY_Z, z);

	// create Sample
	SCSample *pSample = new SCSample();
	pSample->SetType(SCSample::SLEEP_ACCELEROMETER_DATA);
	pSample->SetXaxis(x);
	pSample->SetYaxis(y);
	pSample->SetZaxis(z);
	pSample->SetTime(SCHelpers::GetCurrentTime());

	//compute samples
	pSample->SetEnergy(this->ComputeEnergy(this->pLastSample, pSample));

	//add to resample
	pSleepViewSample = this->pSleepViewResampler->AddSample(pSample);
	pDataSample = this->pDataResampler->AddSample(pSample);

	if(pSleepViewSample != NULL)
	{
		//add to sleepView
		this->pSleepView->AddSample(pSleepViewSample);
		if(SCFormManager::screenSaver && !SCFormManager::appOnBackground)
		{
			//this->pScreenSaver->Show();
		}
	}

	if(pDataSample != NULL)
	{
		//add to data collector
		this->pDataCollector->AddSample(pDataSample);

		//update SampleCount
		if(!SCFormManager::screenSaver)
		{
			String sampleCountStr;
			sampleCountStr.Append(this->pDataCollector->GetSession()->GetSamplesCount());
			this->pSamplesCount->SetText(sampleCountStr);
			this->pSamplesCount->RequestRedraw(true);
		}
	}

	if(this->pLastSample != NULL)
	{
		delete this->pLastSample;
	}

	this->pLastSample = pSample;
}

float
FormCatchSleep::ComputeEnergy(SCSample *pLastSample, SCSample *pCurrentSample)
{
	float energy = 0;

	if(pLastSample != NULL)
	{
		float diffX = pCurrentSample->GetXaxis() - pLastSample->GetXaxis();
		float diffY = pCurrentSample->GetYaxis() - pLastSample->GetYaxis();
		float diffZ = pCurrentSample->GetZaxis() - pLastSample->GetZaxis();

		energy = Math::Sqrt(Math::Pow(diffX, 2) + Math::Pow(diffY, 2) + Math::Pow(diffZ, 2));
	}

	return energy;
}

void
FormCatchSleep::SetActiveAlarm()
{
	String alarmTime;
	this->pActiveSCAlarm = SCAlarm::GetFirstActive();
	if(this->pActiveSCAlarm != NULL)
	{
		alarmTime = SCHelpers::ConvertDateTimeToString(this->pActiveSCAlarm->GetTime(), "HH:mm");
	} else {
		alarmTime.Append(SCTranslator::GetText("IDS_CATCHSLEEP_NOACTIVEALARM"));
	}
	this->pAlarmText->SetText(alarmTime);
}

void
FormCatchSleep::SetCurrentDateTime()
{
	DateTime dt = SCHelpers::GetCurrentTime();
	String dateTimeStr = SCHelpers::ConvertDateTimeToString(dt, "dd.MM.");

	this->pDateText->SetText(dateTimeStr);
}

int
FormCatchSleep::GetFormId()
{
	return SCFormManager::IDF_CATCH_SLEEP;
}

void
FormCatchSleep::RemoveListeners()
{
	this->pSensorManager->RemoveSensorListener(*this);
}

void
FormCatchSleep::StartCatch()
{
	// init proms
	this->pLastSample = NULL;
	this->pSamplesCount->SetText("0");

	//Resamplers
	this->pSleepViewResampler->StartCatch();
	this->pDataResampler->StartCatch();

	//initialize FirstActiveAlarm
	this->SetActiveAlarm();

	//init currentDateTime;
	this->SetCurrentDateTime();

	//create pDataCollector
	this->pDataCollector->SetAlarm(this->pActiveSCAlarm);
	this->pDataCollector->StartCatch();

	//SleepView
	this->pSleepView->StartCatch();

	//Set timer
	this->pTimer = new Timer();
	this->pTimer->Construct(*this);
	this->pTimer->Start(30000);

	//initialize Sensors
	this->InitializeSensors();

	//initialize PowerManager
	PowerManager::KeepScreenOnState(true, true);

	//set catch started
	this->isCatchStart = true;
}

void
FormCatchSleep::StopCatch()
{
	// remove listeners
	this->RemoveListeners();

	//remove Timer
	delete this->pTimer;
	this->pTimer = NULL;

	// set stop info
	this->pDataCollector->StopCatch();
	this->pSleepView->StopCatch();
	this->pSleepViewResampler->StopCatch();
	this->pDataResampler->StopCatch();

	// power management
	PowerManager::KeepScreenOnState(false, false);

	//stop screenSaver
	if(SCFormManager::screenSaver)
	{
		this->StopScreenSaver();
	}

	// Delete lastSample
	if(this->pLastSample != NULL)
	{
		delete this->pLastSample;
		this->pLastSample = NULL;
	}

	//set catch stopped
	this->isCatchStart = false;
}

void
FormCatchSleep::Update()
{
	//Set active tab
	SCNavigator::SetActiveTab(this->GetTab(), SCFormManager::IDF_CATCH_SLEEP);
}

void
FormCatchSleep::Redraw()
{
	this->Update();
	RequestRedraw(true);
}
